package com.boilermaker.lotterysystem.service.statusconvert.Impl;

import com.boilermaker.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import com.boilermaker.lotterysystem.common.exception.ServiceException;
import com.boilermaker.lotterysystem.service.ActivityService;
import com.boilermaker.lotterysystem.service.dto.ActivityDetailDTO;
import com.boilermaker.lotterysystem.service.statusconvert.StatusConvertManager;
import com.boilermaker.lotterysystem.service.dto.ConvertStatusDTO;
import com.boilermaker.lotterysystem.service.statusconvert.operator.AbstractStatusOperator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Service
@Slf4j
public class StatusConvertManagerImpl implements StatusConvertManager {

    @Autowired
    private ActivityService activityService;

    /**
     * 将每个需要转换的状态注册为其相应的 StatusOperator。
     * 结构：key -> OperatorName, val -> StatusOperator
     */
    private final Map<String, AbstractStatusOperator> operatorMap;

    @Autowired // 构造器注入
    public StatusConvertManagerImpl(Map<String, AbstractStatusOperator> operatorMap) {
        // Spring 在构造器注入 Map 时，默认将 bean 的名称作为 key，bean 实例作为 value
        this.operatorMap = operatorMap;
    }

    /**
     * 状态转换流程控制器
     */
    @Override
    public void manageStatusConvert(ConvertStatusDTO dto) {

        if (CollectionUtils.isEmpty(operatorMap)) {
            log.warn("operatorMap 为空");
            return;
        }

        // 得到一个 OperatorMap 的副本
        Map<String, AbstractStatusOperator> tempOperatorMap = new HashMap<>(operatorMap);

        // 按责任链处理
        // sequence1 : 人员、奖品状态扭转
        boolean sequence1Success = convertBySequence(dto, tempOperatorMap, 1);
        if (!sequence1Success) {
            log.error("人员、奖品状态扭转失败");
            throw new ServiceException(ServiceErrorCodeConstants.STATUS_CONVERT_ERROR);
        }

        // sequence2 : 活动状态扭转（活动状态扭转需要依赖其他状态）
        boolean sequence2Success = convertBySequence(dto, tempOperatorMap, 2);
        if (!sequence2Success) {
            log.error("活动状态扭转失败");
            throw new ServiceException(ServiceErrorCodeConstants.STATUS_CONVERT_ERROR);
        }

        // 更新缓存
        ActivityDetailDTO activityDetailDTO = activityService.getActivityDetailDTO(dto.getActivityId());
        boolean ok = activityService.cacheActivity(activityDetailDTO);

        if (!ok) {
            log.error("缓存状态扭转失败");
            throw new ServiceException(ServiceErrorCodeConstants.STATUS_CONVERT_ERROR);
        }
    }

    /**
     * 完成状态转换的一个 sequence：
     * 调用所有处于该 sequence 的 StatusOperator 的 Convert 方法。
     */
    private boolean convertBySequence(ConvertStatusDTO dto,
                                      Map<String, AbstractStatusOperator> tempOperatorMap,
                                      int sequence) {

        // 筛选出指定 sequence 的 operator
        Map<String, AbstractStatusOperator> sequenceOperators =
                filterOperatorsBySequence(tempOperatorMap, sequence);

        if (sequenceOperators.isEmpty()) {
            log.warn("没有找到任何处于第 {} 流程的状态转换器", sequence);
            return true;
        }

        // 执行所有筛选出的处理器
        for (Map.Entry<String, AbstractStatusOperator> entry : sequenceOperators.entrySet()) {
            AbstractStatusOperator operator = entry.getValue();

            if (!operator.convertPolicy(dto)) {
                log.info("状态转换器 {} 不满足转换策略", entry.getKey());
            } else {
                log.info("状态转换器 {} 正在进行转换", entry.getKey());
                Boolean ok = operator.convert(dto);
                if (!ok) {
                    log.error("状态转换器 {} 处理失败", entry.getKey());
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * 从 tempOperatorMap 中筛选出指定 sequence 的状态转换器，
     * 并将筛选出的状态转换器从 tempOperatorMap 中删除。
     *
     * @return 包含指定 sequence 状态转换器的 Map
     */
    private Map<String, AbstractStatusOperator> filterOperatorsBySequence(
            Map<String, AbstractStatusOperator> tempOperatorMap, int targetSequence) {

        Map<String, AbstractStatusOperator> resultMap = new HashMap<>();

        // 使用迭代器安全删除元素
        Iterator<Map.Entry<String, AbstractStatusOperator>> iterator =
                tempOperatorMap.entrySet().iterator();

        while (iterator.hasNext()) {
            // 拿到 Entry
            Map.Entry<String, AbstractStatusOperator> entry = iterator.next();
            // 拿到 Value
            AbstractStatusOperator operator = entry.getValue();

            Integer sequence = operator.sequence();
            if (sequence != null && sequence == targetSequence) {
                resultMap.put(entry.getKey(), operator); // 放入 resultMap
                iterator.remove(); // 安全删除
            }
        }

        return resultMap;
    }
}
